/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package stud.cp.user.userqueries;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.logging.Level;
import javax.ejb.Stateless;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import stud.cp.core.dbaccess.DAOException;
import stud.cp.core.plugins.PluginConst;
import stud.cp.core.plugins.PluginRouter;
import stud.cp.core.plugins.WrongPageRequest;
import stud.cp.user.dbaccess.*;
import stud.cp.user.valueobjects.*;

/**
 * Класс плагин, реализующий бизнес логику для пользовательских зарпосов к базе
 * данных оружия.
 *
 * @author Morfant
 */
@Stateless
public class UserQueriesPluginBean implements UserQueriesPluginLocal {

    /**
     * Фабрика DAO классов.
     */
    private OracleDAOFactory oracleDAOFactory = null;
    /**
     * Логгер.
     */
    private static Logger logger = Logger.getLogger("CPTNP");

    /**
     * Метод, реализующий основную бизнеслогику.
     *
     * @param req Реквест.
     * @return Класс роутер.
     */
    @Override
    public PluginRouter perform(HttpServletRequest req) {
        String subaction = req.getParameter(PluginConst.SUBACTION);
        if ((subaction != null) && (!subaction.equals(""))) {
            try {
                oracleDAOFactory = new OracleDAOFactory();
                oracleDAOFactory.initialize();

                /*
                 * Список действий которые могут выполниться.
                 */
                /*
                 * Список данных
                 */
                if (subaction.equals(PluginConst.GET_LIST)) {
                    return getListPage(req);
                }

                /*
                 * Старница с отчетом о количестве пользователей каждого типа.
                 */
                if (subaction.equals(PluginConst.GET_REVENUE_AND_PRIME_CONST)) {
                    return getRevenueAndPrimeConst(req);
                }
                /*
                 * Старница с отчетом о количестве пользователей каждого типа.
                 */
                if (subaction.equals(PluginConst.GET_REVENUE_AND_PRIME_CONST_REPORT)) {
                    return getRevenueAndPrimeConstReport(req);
                }

                if (subaction.equals(PluginConst.GET_ENDING_OR_MISSING_PRODUCT)) {
                    return getEndingOrMissingProduct(req);
                }

                if (subaction.equals(PluginConst.GET_ENDING_OR_MISSING_PRODUCT_REPORT)) {
                    return getEndingOrMissingProductReport(req);
                }

                if (subaction.equals(PluginConst.GET_CONSUMPTION)) {
                    return getConsumption(req);
                }

                if (subaction.equals(PluginConst.GET_CONSUMPTION_REPORT)) {
                    return getConsumptionReport(req);
                }

                if (subaction.equals(PluginConst.GET_POPULAR_OR_NOT_DISHES)) {
                    return getPopularOrNotDishes(req);
                }

                if (subaction.equals(PluginConst.GET_POPULAR_OR_NOT_DISHES_REPORT)) {
                    return getPopularOrNotDishesReport(req);
                }


                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "Действия для данного типа поддействия не найдено. Тип поддействия = " + subaction);
            } catch (DAOException ex) {
                logger.debug("Error due access to database. "
                        + "Plugin = PropertyGroupPluginBean. "
                        + "Subaction=" + subaction, ex);
                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "Ошибка доступа к данным. " + ex.getMessage());
            } catch (WrongPageRequest ex) {
                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "Данные из реквеста ошибочны :\n" + ex.getMessage());
            } finally {
                if (oracleDAOFactory != null) {
                    try {
                        oracleDAOFactory.cleanUp();
                    } catch (DAOException ex) {
                        logger.debug("Error due access to database. "
                                + "Plugin = PropertyGroupPluginBean. "
                                + "Subaction=" + subaction, ex);
                        req.setAttribute(PluginConst.ERROR_MESSAGE,
                                "Ошибка доступа к данным. " + ex.getMessage());
                    }
                }
            }
        } else {
            req.setAttribute(PluginConst.ERROR_MESSAGE,
                    "Тип поддействия не задан.");
        }
        return new PluginRouter("/errorpage.jsp");
    }

    /**
     * Метод, который позволяет получить список данных запрашиваемого типа.
     *
     * @param req Реквест.
     * @return PluginRouter на страницу в который будет выводиться список.
     * @throws DAOException Ошибки доступа к базе данных.
     */
    private PluginRouter getListPage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        return new PluginRouter("/UserQueries/QueriesTable.jsp");
    }

    /**
     * Метод, который позволяет получить отчет по количеству пользователей
     * каждого типа.
     *
     * @param req Реквест.
     * @return PluginRouter на страницу в который будет выводиться список.
     * @throws DAOException Ошибки доступа к базе данных.
     */
    private PluginRouter getUserCountByTypePage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        req.setAttribute(PluginConst.RESULT, oracleDAOFactory.getUserQueriesDAO().getUserCountByType());
        return new PluginRouter("/UserQueries/CountOfUserByType.jsp");
    }

    /**
     * Метод, который позволяет получить список пользователей.
     *
     * @param req Реквест.
     * @return PluginRouter на страницу в который будет выводиться список.
     * @throws DAOException Ошибки доступа к базе данных.
     */
    private PluginRouter getUserSelectorPage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        req.setAttribute(PluginConst.USERS_LIST, oracleDAOFactory.getUserDAO().getAll());
        return new PluginRouter("/UserQueries/UserSelector.jsp");
    }

    /**
     * Метод, который позволяет просмотреть историю изменения данных об оружии
     * конкретного пользователя.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter getHistoryPageForUser(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String user_id = req.getParameter(PluginConst.USER_ID);
        if (user_id != null) {
            User user =
                    oracleDAOFactory.getUserDAO().getById(new BigInteger(user_id));
            if (user != null) {
                List<History> weaponHistory =
                        oracleDAOFactory.getUserQueriesDAO().getAllHistoryForUser(user.getUserID());
                req.setAttribute(PluginConst.CURRENT_USER, user);
                req.setAttribute(PluginConst.HISTORY_LIST, weaponHistory);
                return new PluginRouter("/UserQueries/UserHistoryTable.jsp");
            } else {
                throw new WrongPageRequest("Пользователя с таким id=" + user_id + " не существует. ");
            }
        } else {
            throw new WrongPageRequest("ID типа оружия не заданно.");
        }
    }

    /**
     * Метод, который позволяет получить страницу с выбором даты изменений.
     *
     * @param req Реквест.
     * @return PluginRouter на страницу в который будет выводиться список.
     * @throws DAOException Ошибки доступа к базе данных.
     */
    private PluginRouter getDateSelectorPage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        return new PluginRouter("/UserQueries/DateSelector.jsp");
    }

    /**
     * Метод, который позволяет просмотреть историю изменения данных по
     * определенной дате.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter getChangeSetForDatePage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String dateInString = req.getParameter(PluginConst.SELECT_DATE);
        if (dateInString != null) {
            //Преобразование даты из строки в дату и т.п. действия.
            DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
            try {
                Date date = df.parse(dateInString);
                List<History> weaponHistory =
                        oracleDAOFactory.getUserQueriesDAO().getAllHistoryForDate(date);
                req.setAttribute(PluginConst.SELECT_DATE, dateInString);
                req.setAttribute(PluginConst.HISTORY_LIST, weaponHistory);
                return new PluginRouter("/UserQueries/DateHistoryTable.jsp");
            } catch (ParseException ex) {
                throw new WrongPageRequest("Формат даты не верен.");
            }


        } else {
            throw new WrongPageRequest("Дата не заданна.");
        }
    }

    /**
     * Метод, который позволяет получить список групп для выбора одной.
     *
     * @param req Реквест.
     * @return PluginRouter на страницу в который будет выводиться список.
     * @throws DAOException Ошибки доступа к базе данных.
     */
    private PluginRouter getGroupSelectorPage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        req.setAttribute(PluginConst.PROPERTY_GROUPS_LIST, oracleDAOFactory.getPropertyGroupsDAO().getAll());
        return new PluginRouter("/UserQueries/GroupSelector.jsp");
    }

    /**
     * Метод, который позволяет просмотреть свойства для конкретной группы.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter getPropertiesForGroupPage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String property_group_id = req.getParameter(PluginConst.PROPERTY_GROUP_ID);
        if (property_group_id != null) {
            PropertyGroup propertyGroup =
                    oracleDAOFactory.getPropertyGroupsDAO().getById(new BigInteger(property_group_id));
            if (propertyGroup != null) {
                List<Property> propertiesList =
                        oracleDAOFactory.getUserQueriesDAO().
                        getAllPropertyForPropertyGroup(propertyGroup.getProperty_group_id());
                req.setAttribute(PluginConst.PROPERTY_GROUP, propertyGroup);
                req.setAttribute(PluginConst.PROPERTIES_LIST, propertiesList);
                return new PluginRouter("/UserQueries/PropertiesForGroup.jsp");
            } else {
                throw new WrongPageRequest("Группы с таким id=" + property_group_id + " не существует. ");
            }
        } else {
            throw new WrongPageRequest("ID группы свойств не заданно.");
        }
    }

    /**
     * Метод, который позволяет получить список свойств для выбора.
     *
     * @param req Реквест.
     * @return PluginRouter на страницу в который будет выводиться список.
     * @throws DAOException Ошибки доступа к базе данных.
     */
    private PluginRouter getPropertySelectorPage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        req.setAttribute(PluginConst.PROPERTIES_LIST, oracleDAOFactory.getPropertiesDAO().getAll());
        return new PluginRouter("/UserQueries/PropertiesSelector.jsp");
    }

    /**
     * Метод, который позволяет просмотреть число оружия определенного типа для
     * свойства..
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter getWeaponCountAndTypeForProperty(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String property_Id = req.getParameter(PluginConst.PROPERTY_ID);
        if (property_Id != null) {
            Property property =
                    oracleDAOFactory.getPropertiesDAO().getById(new BigInteger(property_Id));
            if (property != null) {
                req.setAttribute(PluginConst.PROPERTY, property);
                req.setAttribute(PluginConst.RESULT,
                        oracleDAOFactory.getUserQueriesDAO().getWeaponCountAndTypeForProperty(property.getProperty_id()));
                return new PluginRouter("/UserQueries/WeaponCountAndType.jsp");
            } else {
                throw new WrongPageRequest("Свойства с таким id=" + property_Id + " не существует. ");
            }
        } else {
            throw new WrongPageRequest("ID группы свойств не заданно.");
        }
    }

    /**
     * Метод, который позволяет получить список свойств для выбора.
     *
     * @param req Реквест.
     * @return PluginRouter на страницу в который будет выводиться список.
     * @throws DAOException Ошибки доступа к базе данных.
     */
    private PluginRouter getPropertyListSelectorPage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        req.setAttribute(PluginConst.PROPERTIES_LIST, oracleDAOFactory.getPropertiesDAO().getAll());
        return new PluginRouter("/UserQueries/PropertiesListSelector.jsp");
    }

    /**
     * Метод, который позволяет просмотреть типы оружия для набора запрашиваемых
     * свойств.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter getWeaponTypesForProperties(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String[] property_Ids = req.getParameterValues(PluginConst.PROPERTIES_ID);
        if (property_Ids != null) {
            List<BigInteger> listOfIDs = new LinkedList<BigInteger>();
            int lenght = property_Ids.length;
            BigInteger value;
            for (int i = 0; i < lenght; i++) {
                value = new BigInteger(property_Ids[i]);
                listOfIDs.add(value);
            }
            List<Property> listOfProperty = oracleDAOFactory.getUserQueriesDAO().getAllPropertyForIDs(listOfIDs);
            if (listOfProperty.size() == listOfIDs.size()) {
                req.setAttribute(PluginConst.PROPERTIES_LIST, listOfProperty);
                req.setAttribute(PluginConst.RESULT,
                        oracleDAOFactory.getUserQueriesDAO().getWeaponTypeForProperties(listOfIDs));
                return new PluginRouter("/UserQueries/WeaponTypeForProperties.jsp");
            } else {
                throw new WrongPageRequest("Не все запрашиваемые свойства существуют. ");
            }
        } else {
            throw new WrongPageRequest("ID свойств не заданно.");
        }
    }

    /**
     * Метод, который позволяет получить список групп для выбора одной.
     *
     * @param req Реквест.
     * @return PluginRouter на страницу в который будет выводиться список.
     * @throws DAOException Ошибки доступа к базе данных.
     */
    private PluginRouter getGroupSelectorForWeaponPage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        req.setAttribute(PluginConst.PROPERTY_GROUPS_LIST, oracleDAOFactory.getPropertyGroupsDAO().getAll());
        return new PluginRouter("/UserQueries/GroupSelectorForWeapon.jsp");
    }

    /**
     * Метод, который позволяет просмотреть число оружия определенного типа для
     * группы..
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter getWeaponCountAndTypeForGroup(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String property_group_id = req.getParameter(PluginConst.PROPERTY_GROUP_ID);
        if (property_group_id != null) {
            PropertyGroup property_group =
                    oracleDAOFactory.getPropertyGroupsDAO().getById(new BigInteger(property_group_id));
            if (property_group != null) {
                req.setAttribute(PluginConst.PROPERTY_GROUP, property_group);
                req.setAttribute(PluginConst.RESULT,
                        oracleDAOFactory.getUserQueriesDAO().getWeaponCountAndTypeForGroup(property_group.getProperty_group_id()));
                return new PluginRouter("/UserQueries/WeaponCountAndTypeForGroup.jsp");
            } else {
                throw new WrongPageRequest("Группы с таким id=" + property_group_id + " не существует. ");
            }
        } else {
            throw new WrongPageRequest("ID группы свойств не заданно.");
        }
    }

    private PluginRouter getRevenueAndPrimeConst(HttpServletRequest req) {
        return new PluginRouter("/UserQueries/DateSelector.jsp");
    }

    private PluginRouter getRevenueAndPrimeConstReport(HttpServletRequest req) throws WrongPageRequest, DAOException {
        String dateFrom = req.getParameter(PluginConst.DATE_FROM);
        String dateTo = req.getParameter(PluginConst.DATE_TO);


        //Преобразование даты из строки в дату и т.п. действия.
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date fromDate = df.parse(dateFrom);
            Date toDate = df.parse(dateTo);
            if (toDate.before(fromDate)) {
                String errorMessage = "Дата предшествующая должна быть меньше последующей!";
                req.setAttribute(PluginConst.ERROR_MESSAGE, errorMessage);
                req.setAttribute(PluginConst.DATE_FROM, dateFrom);
                req.setAttribute(PluginConst.DATE_TO, dateTo);
                return new PluginRouter("/UserQueries/DateSelector.jsp");
            } else {
                List<String> results = oracleDAOFactory.getUserQueriesDAO().getRevenueAndPrimeConst(fromDate, toDate);
                req.setAttribute(PluginConst.REPORT_QUERY_RESULT, results);
                return new PluginRouter("/UserQueries/RevenueAndPrimeConstReport.jsp");

            }
        } catch (ParseException ex) {
            throw new WrongPageRequest("Формат даты не верен.");
        }
    }

    private PluginRouter getEndingOrMissingProduct(HttpServletRequest req) {
        return new PluginRouter("/UserQueries/SetEndingBorder.jsp");
    }

    private PluginRouter getEndingOrMissingProductReport(HttpServletRequest req) throws WrongPageRequest, DAOException {
        String numberBorder = req.getParameter(PluginConst.NUMBER_BORDER);
        String weightBorder = req.getParameter(PluginConst.WEIGHT_BORDRE);

        List<BigInteger> productIdList = oracleDAOFactory.getUserQueriesDAO().getEndingOrMissingProductId(numberBorder, weightBorder);

        List<DBObject> productObjectList = new LinkedList<DBObject>();
        Map<BigInteger, Parameter> productStoreParamMap = new HashMap<BigInteger, Parameter>();

        ObjectDAO objectDAO = oracleDAOFactory.getObjectDAO();
        ParametersDAO parametersDAO = oracleDAOFactory.getParameterDAO();
        DBObject product;

        for (BigInteger productId : productIdList) {
            product = objectDAO.getById(productId);
            if (!product.getIsDelete()) {
                productObjectList.add(objectDAO.getById(productId));
                productStoreParamMap.put(productId,
                        parametersDAO.getParameterByIdForObject(PluginConst.STORE_TYPE_PROPERTY_ID,
                        productId));
            }
        }

        req.setAttribute(PluginConst.OBJECT_LIST, productObjectList);
        req.setAttribute(PluginConst.PRODUCT_AMOUNT_MAP, productStoreParamMap);
        return new PluginRouter("/UserQueries/EndingOrMissingProductReport.jsp");

    }

    private PluginRouter getConsumption(HttpServletRequest req) {
        return new PluginRouter("/UserQueries/DateSelector2.jsp");
    }

    private PluginRouter getConsumptionReport(HttpServletRequest req) throws WrongPageRequest, DAOException {
        String dateFrom = req.getParameter(PluginConst.DATE_FROM);
        String dateTo = req.getParameter(PluginConst.DATE_TO);


        //Преобразование даты из строки в дату и т.п. действия.
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date fromDate = df.parse(dateFrom);
            Date toDate = df.parse(dateTo);
            if (toDate.before(fromDate)) {
                String errorMessage = "Дата предшествующая должна быть меньше последующей!";
                req.setAttribute(PluginConst.ERROR_MESSAGE, errorMessage);
                req.setAttribute(PluginConst.DATE_FROM, dateFrom);
                req.setAttribute(PluginConst.DATE_TO, dateTo);
                return new PluginRouter("/UserQueries/DateSelector2.jsp");
            } else {

                Map<BigInteger, String> productAmountMap =
                        oracleDAOFactory.getUserQueriesDAO().
                        getConsumptionReport(fromDate, toDate);

                List<DBObject> productList = new LinkedList<DBObject>();

                Collection<BigInteger> productIdList = productAmountMap.keySet();

                Map<BigInteger, Parameter> productStoreParamMap = new HashMap<BigInteger, Parameter>();

                ObjectDAO objectDAO = oracleDAOFactory.getObjectDAO();
                ParametersDAO parametersDAO = oracleDAOFactory.getParameterDAO();
                DBObject product;
                Parameter param;

                for (BigInteger productId : productIdList) {
                    product = objectDAO.getById(productId);
                    if (!product.getIsDelete()) {
                        productList.add(product);
                        param = parametersDAO.getParameterByIdForObject(PluginConst.STORE_TYPE_PROPERTY_ID, productId);
                        param.setValue(productAmountMap.get(productId));
                        productStoreParamMap.put(productId, param);
                    }
                }
                req.setAttribute(PluginConst.DATE_FROM, dateFrom);
                req.setAttribute(PluginConst.DATE_TO, dateTo);

                req.setAttribute(PluginConst.OBJECT_LIST, productList);
                req.setAttribute(PluginConst.PRODUCT_AMOUNT_MAP, productStoreParamMap);

                return new PluginRouter("/UserQueries/ConsumptionReport.jsp");
            }
        } catch (ParseException ex) {
            throw new WrongPageRequest("Формат даты не верен.");
        }
    }

    private PluginRouter getPopularOrNotDishes(HttpServletRequest req) {
        return new PluginRouter("/UserQueries/DateSelector3.jsp");
    }
    private static final String DISH_XML_ROOT_ELEMENT = "DISH_XML_ROOT_ELEMENT";
    private static final String DISH_XML_PRODUCT_ELEMENT = "DISH_XML_PRODUCT_ELEMENT";
    private static final String DISH_XML_PRODUCT_ID_ATTRIBUTE = "DISH_XML_PRODUCT_ID_ATTRIBUTE";
    private static final String DISH_XML_PRODUCT_AMOUNT_ATTRIBUTE = "DISH_XML_PRODUCT_AMOUNT_ATTRIBUTE";

    private PluginRouter getPopularOrNotDishesReport(HttpServletRequest req) throws WrongPageRequest, DAOException {
        String dateFrom = req.getParameter(PluginConst.DATE_FROM);
        String dateTo = req.getParameter(PluginConst.DATE_TO);
        String notPopularCheckBox = req.getParameter(PluginConst.NOT_POPULAR_CHECK_BOX);

        Boolean isPopular;
        if (notPopularCheckBox != null) {
            isPopular = false;
        } else {
            isPopular = true;
        }

        //Преобразование даты из строки в дату и т.п. действия.
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date fromDate = df.parse(dateFrom);
            Date toDate = df.parse(dateTo);
            if (toDate.before(fromDate)) {
                String errorMessage = "Дата предшествующая должна быть меньше последующей!";
                req.setAttribute(PluginConst.ERROR_MESSAGE, errorMessage);
                req.setAttribute(PluginConst.DATE_FROM, dateFrom);
                req.setAttribute(PluginConst.DATE_TO, dateTo);
                return new PluginRouter("/UserQueries/DateSelector3.jsp");
            } else {

                List<BigInteger> orderIdList = oracleDAOFactory.getUserQueriesDAO().getPopularOrNotDishesId(fromDate, toDate);

                Map<BigInteger, Integer> dishAmountMap = new HashMap<BigInteger, Integer>();

                ObjectDAO objectDAO = oracleDAOFactory.getObjectDAO();
                ParametersDAO parametersDAO = oracleDAOFactory.getParameterDAO();
                Parameter xmlOrder;


                for (BigInteger orderId : orderIdList) {
                    xmlOrder = parametersDAO.getParameterByIdForObject(PluginConst.ORDER_CONSIST_PROPERTY_ID, orderId);

                    String recipeXML = xmlOrder.getValue();
                    SAXBuilder builder = new SAXBuilder();

                    Document document;
                    try {

                        document = builder.build(new ByteArrayInputStream(recipeXML.getBytes()));
                        Element root = document.getRootElement();
                        List<Element> dishElementList = root.getChildren(DISH_XML_PRODUCT_ELEMENT);

                        BigInteger dishID;
                        for (Element productElement : dishElementList) {
                            dishID = new BigInteger(
                                    productElement.getAttributeValue(DISH_XML_PRODUCT_ID_ATTRIBUTE));
                            String dishCount = productElement.getAttributeValue(DISH_XML_PRODUCT_AMOUNT_ATTRIBUTE);
                            if (dishAmountMap.containsKey(dishID)) {
                                dishAmountMap.put(dishID, dishAmountMap.get(dishID) + Integer.valueOf(dishCount));
                            } else {
                                dishAmountMap.put(dishID, Integer.valueOf(dishCount));
                            }
                        }

                    } catch (JDOMException ex) {
                        logger.debug("Ошибка во время разбора рецепта.", ex);
                    } catch (IOException ex) {
                        logger.debug("Ошибка во время разбора рецепта.", ex);
                    }
                }

                Collection<BigInteger> dishIdList = dishAmountMap.keySet();
                DBObject dish;
                Map<BigInteger, DBObject> dishObjectMap = new HashMap<BigInteger, DBObject>();

                List<BigInteger> deletedDishId = new LinkedList<BigInteger>();

                for (BigInteger dishId : dishIdList) {
                    dish = objectDAO.getById(dishId);
                    if (dish.getIsDelete()) {
                        deletedDishId.add(dishId);
                    } else {
                        dishObjectMap.put(dishId, dish);
                    }
                }

                for (BigInteger dishId : deletedDishId) {
                    dishAmountMap.remove(dishId);
                }
                Comparator comparator;
                if (isPopular) {
                    comparator = new ValueComparator(dishAmountMap);
                } else {
                    comparator = new NegativeValueComparator(dishAmountMap);
                }

                SortedMap<BigInteger, Integer> sortDishAmountMap = new TreeMap<BigInteger, Integer>(comparator);
                sortDishAmountMap.putAll(dishAmountMap);

                req.setAttribute(PluginConst.DATE_FROM, dateFrom);
                req.setAttribute(PluginConst.DATE_TO, dateTo);

                req.setAttribute(PluginConst.DISH_MAP, dishObjectMap);
                req.setAttribute(PluginConst.DISH_AMOUNT_MAP, sortDishAmountMap);
                
                req.setAttribute(PluginConst.IS_POPULAR,new Boolean(isPopular));

                return new PluginRouter("/UserQueries/PopularOrNotDishesReport.jsp");
            }
        } catch (ParseException ex) {
            throw new WrongPageRequest("Формат даты не верен.");
        }
    }

    private class ValueComparator implements Comparator {

        Map base;

        public ValueComparator(Map base) {
            this.base = base;
        }

        public int compare(Object a, Object b) {

            if ((Integer) base.get(a) < (Integer) base.get(b)) {
                return 1;
            } else if ((Integer) base.get(a) == (Integer) base.get(b)) {
                return 0;
            } else {
                return -1;
            }
        }
    }

    private class NegativeValueComparator implements Comparator {

        Map base;

        public NegativeValueComparator(Map base) {
            this.base = base;
        }

        public int compare(Object a, Object b) {

            if ((Integer) base.get(a) > (Integer) base.get(b)) {
                return 1;
            } else if ((Integer) base.get(a) == (Integer) base.get(b)) {
                return 0;
            } else {
                return -1;
            }
        }
    }
}
